module notifyclient;
import std.stdio;
import app.utils;
import app.beanstalkd;
import std.experimental.logger;
import hunt.text.configuration, hunt;
import app.model;
import app.service.paybillservice;
import std.conv;
import bootstrap;
import app.model.db;
import std.json;
import app.helper.appinfo;
import std.digest.md;
import core.stdc.time;
import std.string;

const int[] JOB_DELAY_TIME = [4 * 60,10* 60,10* 60, 1 * 60 * 60,2 * 60 * 60,6 * 60 * 60,15 * 60 * 60];//7次 4m,10m,10m,1h,2h,6h,15h
const int[] JOB_DELAY_PRIORITY = [4 * 60,10* 60,10* 60, 1 * 60 * 60,2 * 60 * 60,6 * 60 * 60,15 * 60 * 60];//5次 4m,10m,10m,1h,2h,6h,15h

void main()
{
	initDBStr(buildPGUrl(Config.app.config));
	Tube tube = getStalkdTube();
	
	string tubename = Config.app.config.beanstalkd.tube.value();
	tube.watch(tubename);
	trace("tube.watching:", tube.watching);
	while(true)
	{
		Job job = tube.reserve();
		trace("job id:", job.id, " job data:", job.bodyAsString());
		PayBill bill = PayBillService.getInstance.getByWhere(["id":job.bodyAsString()]);
		if(bill is null || bill.notifySuccessTime !=0){
			warning("not exist or notfiy success bill id:", job.bodyAsString());
			job.destroy();
			continue;
		}

		JSONValue json;
		json["bill_id"] = to!(string)(bill.id);
		json["channel"] = bill.channel;
		json["appid"] = bill.appid;
		json["out_trade_no"] = bill.outTradeNo;
		json["amount"] = bill.amount;
		json["trade_status"]  = bill.status;
		if(bill.passbackParams.length){
			json["passback_params"] = bill.passbackParams;
		}

		string jsonString = json.toString();
		IAppInfo appinfo = new AppInfoInner();
		SAppInfo sinfo = appinfo.getSAppInfoById(bill.appid);
		string signTime = to!(string)(time(null));
		string signedData = aes256Encrypt(json.toString(),sinfo.appSecretKey);
		string sign = toHexString(md5Of(signedData ~ signTime ~ sinfo.appSecretKey));
		//组装数据包头，

		string result = post(bill.notifyUrl,["sign_time":signTime, "data": signedData, "sign": sign]);

		
		//auto result = false;
		///通知没成功
		if(result.indexOf("success") == -1)
		{
			string[string] jobStatus = job.statsJob();
			int releases = to!int(jobStatus["releases"]);
			//通知8从
			if( releases >= 7){

				warning("job is release more than 7 times, will be destroyed:", job.bodyAsString());
				job.destroy();
				continue;
			}
			else{
				job.release(JOB_DELAY_TIME[releases],JOB_DELAY_PRIORITY[releases]);
				trace("release time:",JOB_DELAY_TIME[releases]," priority:", JOB_DELAY_PRIORITY[releases]);
				continue;
			}
		}

		PayBillService.getInstance.updateByWhere(["notify_success_time": to!(string)(time(null))], ["id":to!(string)(bill.id)]);

		job.destroy();	
	}
}
